package com.example.dictionary.service;

import com.example.memento.model.DomainWord;
import com.example.memento.model.ExplanationEntry;
import com.example.memento.model.WordModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

/**
 * DomainWordsDict 解析服务
 * 解析下载的领域词汇字典文件，并保存到数据库
 */
@Service
public class DomainWordsDictParser {
    
    private static final Logger log = LoggerFactory.getLogger(DomainWordsDictParser.class);
    
    // 用于匹配文件名（去除 .txt 扩展名）
    private static final Pattern TXT_FILE_PATTERN = Pattern.compile("(.+)\\.txt$", Pattern.CASE_INSENSITIVE);
    
    // 用于分割行（tab 分隔）
    private static final String TAB_SEPARATOR = "\t";
    
    private final DownloadPathMappingService downloadPathMappingService;
    private final DictionaryDelegate dictionaryDelegate;
    
    // DomainWordsDict 的资源标识符
    private static final String DOMAIN_WORDS_DICT_GIT_URL = "https://github.com/liuhuanyong/DomainWordsDict.git";
    private static final String DOMAIN_WORDS_DICT_BRANCH = "master";
    
    public DomainWordsDictParser(
            DownloadPathMappingService downloadPathMappingService,
            DictionaryDelegate dictionaryDelegate) {
        this.downloadPathMappingService = downloadPathMappingService;
        this.dictionaryDelegate = dictionaryDelegate;
    }
    
    /**
     * 解析 DomainWordsDict 数据
     * 
     * @throws IOException 如果文件不存在或读取失败
     */
    public void parse() throws IOException {
        log.info("开始解析 DomainWordsDict 数据...");
        
        // 1. 从下载映射服务获取文件地址
        String resourceKey = downloadPathMappingService.buildGitHubResourceKey(
                DOMAIN_WORDS_DICT_GIT_URL, DOMAIN_WORDS_DICT_BRANCH);
        Optional<String> downloadPathOpt = downloadPathMappingService.getDownloadPath(resourceKey);
        
        if (downloadPathOpt.isEmpty()) {
            throw new IllegalStateException(
                String.format("DomainWordsDict 下载路径未找到，资源标识符: %s。请先下载资源。", resourceKey)
            );
        }
        
        String downloadPath = downloadPathOpt.get();
        // 如果下载路径指向解压后的目录（如 DomainWordsDict-master），直接使用
        // 否则尝试查找 data 子目录
        Path dataDir = Paths.get(downloadPath);
        if (Files.exists(dataDir) && Files.isDirectory(dataDir)) {
            // 检查是否存在 data 子目录
            Path possibleDataDir = dataDir.resolve("data");
            if (Files.exists(possibleDataDir) && Files.isDirectory(possibleDataDir)) {
                dataDir = possibleDataDir;
            }
        } else {
            throw new IOException("DomainWordsDict 数据目录不存在: " + dataDir);
        }
        
        // 2. 检查路径是否存在
        if (!Files.exists(dataDir)) {
            throw new IOException(
                String.format("DomainWordsDict 数据目录不存在: %s", dataDir.toAbsolutePath())
            );
        }
        
        if (!Files.isDirectory(dataDir)) {
            throw new IOException(
                String.format("指定的路径不是目录: %s", dataDir.toAbsolutePath())
            );
        }
        
        log.info("找到 DomainWordsDict 数据目录: {}", dataDir.toAbsolutePath());
        
        // 3. 遍历所有 .txt 文件
        List<Path> txtFiles = getTxtFiles(dataDir);
        
        if (txtFiles.isEmpty()) {
            log.warn("数据目录中没有找到任何 .txt 文件: {}", dataDir);
            return;
        }
        
        log.info("找到 {} 个领域文件", txtFiles.size());
        
        // 4. 解析每个文件
        int totalWords = 0;
        int totalProcessed = 0;
        
        for (Path txtFile : txtFiles) {
            String domainName = extractDomainName(txtFile);
            log.info("解析领域文件: {} (领域: {})", txtFile.getFileName(), domainName);
            
            try {
                int processed = parseDomainFile(txtFile, domainName);
                totalProcessed += processed;
                totalWords += processed;
                // log.info("✓ 完成解析领域 {}，处理 {} 个词汇", domainName, processed);
            } catch (Exception e) {
                log.error("解析领域文件失败: {} (领域: {})", txtFile, domainName, e);
                throw e;
            }
        }
        
        log.info("DomainWordsDict 解析完成！总计处理 {} 个词汇，涉及 {} 个领域", totalWords, txtFiles.size());
    }
    
    /**
     * 获取所有 .txt 文件
     */
    private List<Path> getTxtFiles(Path dataDir) throws IOException {
        List<Path> txtFiles = new ArrayList<>();
        
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(dataDir, "*.txt")) {
            for (Path path : stream) {
                if (Files.isRegularFile(path)) {
                    txtFiles.add(path);
                }
            }
        }
        
        return txtFiles;
    }
    
    /**
     * 从文件名提取领域名称（去除 .txt 扩展名）
     */
    private String extractDomainName(Path file) {
        String fileName = file.getFileName().toString();
        java.util.regex.Matcher matcher = TXT_FILE_PATTERN.matcher(fileName);
        if (matcher.matches()) {
            return matcher.group(1);
        }
        return fileName;
    }
    
    /**
     * 解析单个领域文件
     * 
     * @param file 文件路径
     * @param domainName 领域名称
     * @return 处理的词汇数量
     */
    private int parseDomainFile(Path file, String domainName) throws IOException {
        int processedCount = 0;
        int lineNumber = 0;
        
        try (var lines = Files.lines(file)) {
            for (String line : lines.toList()) {
                lineNumber++;
                line = line.trim();
                
                // 跳过空行
                if (line.isEmpty()) {
                    continue;
                }
                
                // 解析行：词汇\t权重
                String[] parts = line.split(TAB_SEPARATOR);
                if (parts.length < 1) {
                    log.warn("跳过无效行 {} (文件: {}): {}", lineNumber, file.getFileName(), line);
                    continue;
                }
                
                // 第一个词是词汇
                String word = parts[0].trim();
                if (word.isEmpty()) {
                    continue;
                }
                
                // 权重（可选）
                Integer weight = null;
                if (parts.length >= 2) {
                    try {
                        weight = Integer.parseInt(parts[parts.length - 1].trim());
                    } catch (NumberFormatException e) {
                        // 权重解析失败，使用默认值
                        log.debug("权重解析失败 (行 {}): {}", lineNumber, parts[1]);
                    }
                }
                
                try {
                    // 5. 查询词汇对象
                    Optional<WordModel> wordModelOpt = dictionaryDelegate.findWord(word);
                    
                    WordModel wordModel;
                    if (wordModelOpt.isPresent()) {
                        // 词汇已存在，更新
                        wordModel = wordModelOpt.get();
                    } else {
                        // 创建新的词汇对象
                        wordModel = WordModel.builder()
                                .primaryWord(word)
                                .language("zh-CN")
                                .frequency(weight)
                                .build();
                    }

                    wordModel.addDomainWordName(domainName);
                    // 6. 将领域名称加入到词汇对象中

                    // 7. 调用保存函数
                    dictionaryDelegate.saveWord(wordModel);
                    processedCount++;
                    
                    // 每处理 1000 个词汇记录一次
                    if (processedCount % 1000 == 0) {
                        // log.debug("已处理 {} 个词汇 (领域: {})", processedCount, domainName);
                    }
                    
                } catch (Exception e) {
                    log.error("处理词汇失败 (行 {}): {} (领域: {})", lineNumber, word, domainName, e);
                    // 继续处理下一个词汇，不中断整个解析过程
                }
            }
        }
        
        return processedCount;
    }
    
    /**
     * 解析指定领域的文件
     * 
     * @param domainName 领域名称（文件名，不含 .txt）
     * @throws IOException 如果文件不存在或读取失败
     */
    public void parseDomain(String domainName) throws IOException {
        log.info("开始解析领域: {}", domainName);
        
        // 获取数据目录
        String resourceKey = downloadPathMappingService.buildGitHubResourceKey(
                DOMAIN_WORDS_DICT_GIT_URL, DOMAIN_WORDS_DICT_BRANCH);
        Optional<String> downloadPathOpt = downloadPathMappingService.getDownloadPath(resourceKey);
        
        if (downloadPathOpt.isEmpty()) {
            throw new IllegalStateException("DomainWordsDict 下载路径未找到");
        }
        
        Path dataDir = Paths.get(downloadPathOpt.get());
        // 检查是否存在 data 子目录
        Path possibleDataDir = dataDir.resolve("data");
        if (Files.exists(possibleDataDir) && Files.isDirectory(possibleDataDir)) {
            dataDir = possibleDataDir;
        }
        
        if (!Files.exists(dataDir)) {
            throw new IOException("DomainWordsDict 数据目录不存在: " + dataDir);
        }
        
        Path domainFile = dataDir.resolve(domainName + ".txt");
        
        if (!Files.exists(domainFile)) {
            throw new IOException("领域文件不存在: " + domainFile);
        }
        
        int processed = parseDomainFile(domainFile, domainName);
        log.info("完成解析领域 {}，处理 {} 个词汇", domainName, processed);
    }
}

